package com.shop.shop.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.shop.shop.dao.GoodMapper;
import com.shop.shop.dao.OrderMapper;
import com.shop.shop.model.Chart;
import com.shop.shop.model.Order;
import com.shop.shop.service.userfeign.UserFeign;
import com.shop.shop.util.RedisLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.ResponseBody;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import javax.annotation.Resource;

@Service
public class OrderService {
    @Resource
    OrderMapper orderMapper;
    @Resource
    RedisLock redisLock;
    @Resource
    JedisPool jedisPool;
    @Resource
    GoodMapper goodMapper;

    @Autowired
    UserFeign userFeign;
    public Order createOrderByChart(Chart chart){
        Order order=new Order();
        return order;
    }

    //生成秒杀订单
    public Order createSecKillOrder(Long uid, Long gid){
        Order order=null;
        Boolean userAvailable=false;
        userAvailable=UserAvailable(uid);
        //确认账户存在
        if (!userAvailable){
            order=new Order();
            order.setOid("error");
            return order;
        }
        Jedis jedis=jedisPool.getResource();
        Integer rest = Integer.valueOf(jedisPool.getResource().hget("restore", gid.toString()));
        if (rest>0){
            Integer count =0;//记录获取锁的次数
            String lock;
            while (count<3){//循环3次，失败重新抢
                lock=redisLock.tryLock(gid.toString(),String.valueOf(Thread.currentThread().hashCode())+":1","ES",5);
                count++;
                if ("OK".equals(lock)){
                    Long restore=goodMapper.getRetore(gid);
                    //获取锁之后再去查看数据库，因为缓存中的数据并不是完全可信
                    if (restore>0){
                        //下单成功
                        //应该把扣除库存操作包装成一个事务，成功的话继续执行，生成订单，将消息加入消息队列，
                        String oid=jedis.get(gid.toString()+uid.toString());
                        if (oid!=null){//如果已经存在订单
                            order=new Order();
                            order.setOid(jedis.get(gid.toString()+uid.toString()));
                            redisLock.tryRelease(gid.toString());
                            return order;
                        }else {
                            oid=gid.toString()+uid.toString();
                            jedis.hset("restore",gid.toString(),String.valueOf(rest-1));//刷新缓存，先扣库存
                            jedis.set(jedis.get(gid.toString()+uid.toString()),"order message");//包含下单时间，订单价格，订单是否被消费

                            redisLock.tryRelease(gid.toString());
                        }
                        /**
                         * @Description:中间添加其他系统功能，如发短信，积分计算等异步功能，考虑使用消息队列
                         * @Param: [goodID, userId]
                         * @returns: java.lang.String
                         * @Author: ypc
                         * @Date: 2021/4/12 16:57
                         * @packageName: com.shop.shop.service
                         */
                        //最简单的队列，lpush()..
                        //

                    } else {
                        //数据库库存为0时刷新缓存
                        jedis.hset("restore",gid.toString(),"0");
                        redisLock.tryRelease(gid.toString());

                    }
                }
            }
        }
        return order;
    }

    //支付秒杀订单
    public void paySecKillOrder(String oid){
        Jedis jedis=jedisPool.getResource();
        String oidMessage=jedis.get(oid);
        if ("已经支付".equals(oidMessage)){//暂时未完成oidMessage结构的构造，伪条件，获取订单是否支付信息
            return;
        }else {
            String lock=redisLock.tryLock(oid+"paying","value","ES",5);
            //获取到锁继续执行，否则退出
            if ("OK".equals(lock)){
                if ("已经支付".equals(jedis.get(oid))){//双重确认
                    return;
                } else {
                    //进行支付操作，修改订单信息为已经完成，之后释放锁，再之后将其他任务加入消息队列
                    //付钱操作，作为事务，成功继续，失败的话返回失败
                    Boolean pay=true;//获取账户信息锁，进行金额扣除操作。暂未实现
                    if (pay){
                        jedis.set(oid,"已经支付");
                        redisLock.tryRelease(oid+"paying");
                        //其他操作，加入消息队列，进行功能模块的异步解耦
                    } else {
                        return;
                    }
                }
            }
            return;
        }
    }

    @HystrixCommand(fallbackMethod = "createSecKillOrderError")
    public Boolean UserAvailable(Long uid){
        return userFeign.isUserAvailable(uid);
    }

    public Boolean createSecKillOrderError(Long uid){
        return false;
    }

    public String a(){
        return userFeign.get();
    }
}
